#pragma once

#include <iostream>
#include <string>
#include <cstdarg>  // 可变参数列表需要的头文件
#include <ctime>
#include <unistd.h>

#include <time.h>   // 时间戳转化需要的头文件

#define DEBUG 0
#define NORMAL 1
#define WARNING 2
#define ERROR 3
#define FATAL 4

// 对应的数字转成对应的字符串
const char* to_levelstr(int level){
    switch(level){
        case DEBUG: return "DEBUG";
        case NORMAL: return "NORMAL";
        case WARNING: return "WARNING";
        case ERROR: return "ERROR";
        case FATAL: return "FATAL";
        default: return nullptr;
    }
}

#define LOG_NORMAL "log.txt"
#define LOG_ERROR "log.error"

void logMessage(int level, const char* format, ...){
    // [日志等级] [时间戳/时间] [pid] [messge]
    // [WARNING] [2023-05-11 18:09:08] [123] [创建socket失败]
    // va_list start;    
    // va_start(start);
    // while(*p){
    //     switch(*p)
    //     {
    //         case '%':
    //             p++;
    //             if(*p == 'f') arg = va_arg(start, float);
    //         ...
    //     }
    // }
    // va_end(start);

#define NUM 1024
    // 格式化把数据输入到 logprefix 里面去
    // logprefix 字符串记录的是日志的前面部分的内容
    char logprefix[NUM];

    // 时间戳具体的使用：https://blog.csdn.net/qq_42591783/article/details/123539031
    // 把本来 (long int)time(nullptr) 时间戳形式的时间处理成我们日常用的时间的形式
    // time_t 的类型是 long int 的哦
    time_t timeStamp = (long int)time(nullptr);
    struct tm *mytm;
    mytm = gmtime(&timeStamp);

    // snprintf(logprefix, sizeof(logprefix), "[%s][%ld][pid: %d]", 
    //     to_levelstr(level), /*(long int)time(nullptr)*/ mytm->tm_year + 1970,  , getpid());

    // 注意 tm_year 得加上 1900. 因为当前时间戳是距离 1900 年开始的时间来计算的
    // tm_mon 得加上 1， tm_hour 得加上 8 才转化为北京时间
    snprintf(logprefix, sizeof(logprefix), "[%s][%d-%d-%d  %d-%d-%d][pid: %d]", 
        to_levelstr(level), mytm->tm_year + 1900, mytm->tm_mon + 1, mytm->tm_mday, mytm->tm_hour + 8, mytm->tm_min, mytm->tm_sec, getpid());


    // logcontent 字符串记录的是日志信息尾部的内容
    char logcontent[NUM];
    va_list arg;
    va_start(arg, format);
    vsnprintf(logcontent, sizeof(logcontent), format, arg);

    // std:::cout << logprefix << logcontent << std::endl;

    FILE* log = fopen(LOG_NORMAL, "a");
    FILE* err = fopen(LOG_ERROR, "a");  
    if(log != nullptr && err != nullptr){
        // curr 表示的是当前打开的文件指针
        FILE* curr = nullptr;
        if(level == DEBUG || level == NORMAL || level == WARNING) curr = log;
        if(level == ERROR || level == FATAL) curr = err;
        if(curr != nullptr)
            fprintf(curr, "%s%s\n", logprefix, logcontent);

        fclose(log);
        fclose(err);
    }
}
